home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / istack.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  18.2 KB  |  646 lines

  1. /* Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: istack.c,v 1.2 2000/09/19 19:00:46 lpd Exp $ */
  20. /* Manager for expandable stacks of refs */
  21. #include "memory_.h"
  22. #include "ghost.h"
  23. #include "gsstruct.h"
  24. #include "gsutil.h"
  25. #include "errors.h"
  26. #include "ialloc.h"
  27. #include "istack.h"
  28. #include "istkparm.h"
  29. #include "istruct.h"        /* for RELOC_REF_VAR */
  30. #include "iutil.h"
  31. #include "ivmspace.h"        /* for local/global test */
  32. #include "store.h"
  33.  
  34. /* Forward references */
  35. private void init_block(P3(ref_stack_t *pstack, const ref *pblock_array,
  36.                uint used));
  37. private int ref_stack_push_block(P3(ref_stack_t *pstack, uint keep, uint add));
  38.  
  39. /* GC descriptors and procedures */
  40. private_st_ref_stack_params();
  41. private 
  42. CLEAR_MARKS_PROC(ref_stack_clear_marks)
  43. {
  44.     ref_stack_t *const sptr = vptr;
  45.  
  46.     r_clear_attrs(&sptr->current, l_mark);
  47. }
  48. private 
  49. ENUM_PTRS_WITH(ref_stack_enum_ptrs, ref_stack_t *sptr) return 0;
  50. case 0: ENUM_RETURN_REF(&sptr->current);
  51. case 1: return ENUM_OBJ(sptr->params);
  52. ENUM_PTRS_END
  53. private RELOC_PTRS_WITH(ref_stack_reloc_ptrs, ref_stack_t *sptr)
  54. {
  55.     /* Note that the relocation must be a multiple of sizeof(ref_packed) */
  56.     /* * align_packed_per_ref, but it need not be a multiple of */
  57.     /* sizeof(ref).  Therefore, we must do the adjustments using */
  58.     /* ref_packed pointers rather than ref pointers. */
  59.     ref_packed *bot = (ref_packed *) sptr->current.value.refs;
  60.     long reloc;
  61.  
  62.     RELOC_REF_VAR(sptr->current);
  63.     r_clear_attrs(&sptr->current, l_mark);
  64.     reloc = bot - (ref_packed *) sptr->current.value.refs;
  65. #define RELOC_P(p)\
  66.   sptr->p = (ref *)((ref_packed *)sptr->p - reloc);
  67.     RELOC_P(p);
  68.     RELOC_P(bot);
  69.     RELOC_P(top);
  70. #undef RELOC_P
  71.     RELOC_OBJ_VAR(sptr->params);
  72. } RELOC_PTRS_END
  73. /* Structure type for a ref_stack. */
  74. public_st_ref_stack();
  75.  
  76. /* Initialize a stack. */
  77. int
  78. ref_stack_init(ref_stack_t *pstack, const ref *pblock_array,
  79.            uint bot_guard, uint top_guard, const ref *pguard_value,
  80.            gs_ref_memory_t *mem, ref_stack_params_t *params)
  81. {
  82.     uint size = r_size(pblock_array);
  83.     uint avail = size - (stack_block_refs + bot_guard + top_guard);
  84.     ref_stack_block *pblock = (ref_stack_block *)pblock_array->value.refs;
  85.     s_ptr body = (s_ptr)(pblock + 1);
  86.  
  87.     if (params == 0) {
  88.     params = gs_alloc_struct((gs_memory_t *)mem, ref_stack_params_t,
  89.                  &st_ref_stack_params,
  90.                  "ref_stack_alloc(stack.params)");
  91.     if (params == 0)
  92.         return_error(-1);    /* avoid binding in any error codes */
  93.     }
  94.  
  95.     pstack->bot = body + bot_guard;
  96.     pstack->p = pstack->bot - 1;
  97.     pstack->top = pstack->p + avail;
  98.     pstack->current = *pblock_array;
  99.     pstack->extension_size = 0;
  100.     pstack->extension_used = 0;
  101.  
  102.     make_int(&pstack->max_stack, avail);
  103.     pstack->requested = 0;
  104.     pstack->margin = 0;
  105.     pstack->body_size = avail;
  106.  
  107.     pstack->params = params;
  108.     pstack->memory = mem;
  109.  
  110.     params->bot_guard = bot_guard;
  111.     params->top_guard = top_guard;
  112.     params->block_size = size;
  113.     params->data_size = avail;
  114.     if (pguard_value != 0)
  115.     params->guard_value = *pguard_value;
  116.     else
  117.     make_tav(¶ms->guard_value, t__invalid, 0, intval, 0);
  118.     params->underflow_error = -1;
  119.     params->overflow_error = -1;
  120.     params->allow_expansion = true;
  121.     init_block(pstack, pblock_array, 0);
  122.     refset_null_new(pstack->bot, avail, 0);
  123.     make_empty_array(&pblock->next, 0);
  124.     return 0;
  125. }
  126.  
  127. /* Set whether a stack is allowed to expand.  The initial value is true. */
  128. void
  129. ref_stack_allow_expansion(ref_stack_t *pstack, bool expand)
  130. {
  131.     pstack->params->allow_expansion = expand;
  132. }
  133.  
  134. /* Set the error codes for under- and overflow.  The initial values are -1. */
  135. void
  136. ref_stack_set_error_codes(ref_stack_t *pstack, int underflow_error,
  137.               int overflow_error)
  138. {
  139.     pstack->params->underflow_error = underflow_error;
  140.     pstack->params->overflow_error = overflow_error;
  141. }
  142.  
  143. /* Set the maximum number of elements allowed on a stack. */
  144. int
  145. ref_stack_set_max_count(ref_stack_t *pstack, long nmax)
  146. {
  147.     uint nmin = ref_stack_count_inline(pstack);
  148.  
  149.     if (nmax < nmin)
  150.     nmax = nmin;
  151.     if (nmax > max_uint / sizeof(ref))
  152.     nmax = max_uint / sizeof(ref);
  153.     if (!pstack->params->allow_expansion) {
  154.     uint ncur = pstack->body_size;
  155.  
  156.     if (nmax > ncur)
  157.         nmax = ncur;
  158.     }
  159.     pstack->max_stack.value.intval = nmax;
  160.     return 0;
  161. }
  162.  
  163. /*
  164.  * Set the margin between the limit and the top of the stack.
  165.  * Note that this may require allocating a block.
  166.  */
  167. int
  168. ref_stack_set_margin(ref_stack_t *pstack, uint margin)
  169. {
  170.     const ref_stack_params_t *params = pstack->params;
  171.     uint data_size = params->data_size;
  172.  
  173.     if (margin <= pstack->margin) {
  174.     refset_null_new(pstack->top + 1, pstack->margin - margin, 0);
  175.     } else {
  176.     if (margin > data_size >> 1)
  177.         return_error(e_rangecheck);
  178.     if (pstack->top - pstack->p < margin) {
  179.         uint used = pstack->p + 1 - pstack->bot;
  180.         uint keep = data_size - margin;
  181.         int code = ref_stack_push_block(pstack, keep, used - keep);
  182.  
  183.         if (code < 0)
  184.         return code;
  185.     }
  186.     }
  187.     pstack->margin = margin;
  188.     pstack->body_size = data_size - margin;
  189.     pstack->top = pstack->bot + pstack->body_size - 1;
  190.     return 0;
  191. }
  192.  
  193. /* Return the number of elements on a stack. */
  194. uint
  195. ref_stack_count(const ref_stack_t *pstack)
  196. {
  197.     return ref_stack_count_inline(pstack);
  198. }
  199.  
  200. /*
  201.  * Return a pointer to a given element from the stack, counting from
  202.  * 0 as the top element.  If the index is out of range, return 0.
  203.  */
  204. ref *
  205. ref_stack_index(const ref_stack_t *pstack, long idx)
  206. {
  207.     ref_stack_block *pblock;
  208.     uint used = pstack->p + 1 - pstack->bot;
  209.  
  210.     if (idx < 0)
  211.     return NULL;
  212.     if (idx < used)        /* common case */
  213.     return pstack->p - (uint) idx;
  214.     pblock = (ref_stack_block *) pstack->current.value.refs;
  215.     do {
  216.     pblock = (ref_stack_block *) pblock->next.value.refs;
  217.     if (pblock == 0)
  218.         return NULL;
  219.     idx -= used;
  220.     used = r_size(&pblock->used);
  221.     } while (idx >= used);
  222.     return pblock->used.value.refs + (used - 1 - (uint) idx);
  223. }
  224.  
  225. /*
  226.  * Count the number of elements down to and including the first mark.
  227.  * If no mark is found, return 0.
  228.  */
  229. uint
  230. ref_stack_counttomark(const ref_stack_t *pstack)
  231. {
  232.     uint scanned = 0;
  233.     ref_stack_enum_t rsenum;
  234.  
  235.     ref_stack_enum_begin(&rsenum, pstack);
  236.     do {
  237.     uint count = rsenum.size;
  238.     const ref *p = rsenum.ptr + count - 1;
  239.  
  240.     for (; count; count--, p--)
  241.         if (r_has_type(p, t_mark))
  242.         return scanned + (rsenum.size - count + 1);
  243.     scanned += rsenum.size;
  244.     } while (ref_stack_enum_next(&rsenum));
  245.     return 0;
  246. }
  247.  
  248. /*
  249.  * Do the store check for storing 'count' elements of a stack, starting
  250.  * 'skip' elements below the top, into an array.  Return 0 or e_invalidaccess.
  251.  */
  252. int
  253. ref_stack_store_check(const ref_stack_t *pstack, ref *parray, uint count,
  254.               uint skip)
  255. {
  256.     uint space = r_space(parray);
  257.  
  258.     if (space != avm_local) {
  259.     uint left = count, pass = skip;
  260.     ref_stack_enum_t rsenum;
  261.  
  262.     ref_stack_enum_begin(&rsenum, pstack);
  263.     do {
  264.         ref *ptr = rsenum.ptr;
  265.         uint size = rsenum.size;
  266.  
  267.         if (size <= pass)
  268.         pass -= size;
  269.         else {
  270.         int code;
  271.  
  272.         if (pass != 0)
  273.             size -= pass, pass = 0;
  274.         ptr += size;
  275.         if (size > left)
  276.             size = left;
  277.         left -= size;
  278.         code = refs_check_space(ptr - size, size, space);
  279.         if (code < 0)
  280.             return code;
  281.         if (left == 0)
  282.             break;
  283.         }
  284.     } while (ref_stack_enum_next(&rsenum));
  285.     }
  286.     return 0;
  287. }
  288.  
  289. /*
  290.  * Store the top 'count' elements of a stack, starting 'skip' elements below
  291.  * the top, into an array, with or without store/undo checking.  age=-1 for
  292.  * no check, 0 for old, 1 for new.  May return e_rangecheck or
  293.  * e_invalidaccess.
  294.  */
  295. #undef idmemory            /****** NOTA BENE ******/
  296. int
  297. ref_stack_store(const ref_stack_t *pstack, ref *parray, uint count,
  298.         uint skip, int age, bool check, gs_dual_memory_t *idmemory,
  299.         client_name_t cname)
  300. {
  301.     uint left, pass;
  302.     ref *to;
  303.     ref_stack_enum_t rsenum;
  304.  
  305.     if (count > ref_stack_count(pstack) || count > r_size(parray))
  306.     return_error(e_rangecheck);
  307.     if (check) {
  308.     int code = ref_stack_store_check(pstack, parray, count, skip);
  309.  
  310.     if (code < 0)
  311.         return code;
  312.     }
  313.     to = parray->value.refs + count;
  314.     left = count, pass = skip;
  315.     ref_stack_enum_begin(&rsenum, pstack);
  316.     do {
  317.     ref *from = rsenum.ptr;
  318.     uint size = rsenum.size;
  319.  
  320.     if (size <= pass)
  321.         pass -= size;
  322.     else {
  323.         if (pass != 0)
  324.         size -= pass, pass = 0;
  325.         from += size;
  326.         if (size > left)
  327.         size = left;
  328.         left -= size;
  329.         switch (age) {
  330.         case -1:        /* not an array */
  331.         while (size--) {
  332.             from--, to--;
  333.             ref_assign(to, from);
  334.         }
  335.         break;
  336.         case 0:        /* old array */
  337.         while (size--) {
  338.             from--, to--;
  339.             ref_assign_old(parray, to, from, cname);
  340.         }
  341.         break;
  342.         case 1:        /* new array */
  343.         while (size--) {
  344.             from--, to--;
  345.             ref_assign_new(to, from);
  346.         }
  347.         break;
  348.         }
  349.         if (left == 0)
  350.         break;
  351.     }
  352.     } while (ref_stack_enum_next(&rsenum));
  353.     r_set_size(parray, count);
  354.     return 0;
  355. }
  356.  
  357. /*
  358.  * Pop the top N elements off a stack.
  359.  * The number must not exceed the number of elements in use.
  360.  */
  361. void
  362. ref_stack_pop(ref_stack_t *pstack, uint count)
  363. {
  364.     uint used;
  365.  
  366.     while ((used = pstack->p + 1 - pstack->bot) < count) {
  367.     count -= used;
  368.     pstack->p = pstack->bot - 1;
  369.     ref_stack_pop_block(pstack);
  370.     }
  371.     pstack->p -= count;
  372. }
  373.  
  374. /* Pop the top block off a stack.  May return underflow_error. */
  375. int
  376. ref_stack_pop_block(ref_stack_t *pstack)
  377. {
  378.     s_ptr bot = pstack->bot;
  379.     uint count = pstack->p + 1 - bot;
  380.     ref_stack_block *pcur =
  381.     (ref_stack_block *) pstack->current.value.refs;
  382.     ref_stack_block *pnext =
  383.     (ref_stack_block *) pcur->next.value.refs;
  384.     uint used;
  385.     ref *body;
  386.     ref next;
  387.  
  388.     if (pnext == 0)
  389.     return_error(pstack->params->underflow_error);
  390.     used = r_size(&pnext->used);
  391.     body = (ref *) (pnext + 1) + pstack->params->bot_guard;
  392.     next = pcur->next;
  393.     /*
  394.        * If the contents of the two blocks won't fit in a single block, we
  395.        * move up the used part of the top block, and copy up as much of
  396.        * the contents of the next block under it as will fit.  If the
  397.        * contents of both blocks fit in a single block, we copy the used
  398.        * part of the top block to the top of the next block, and free the
  399.        * top block.
  400.      */
  401.     if (used + count > pstack->body_size) {
  402.     /*
  403.      * The contents of the two blocks won't fit into a single block.
  404.      * On the assumption that we're recovering from a local stack
  405.      * underflow and need to increase the number of contiguous
  406.      * elements available, move up the used part of the top block, and
  407.      * copy up as much of the contents of the next block under it as
  408.      * will fit.
  409.      */
  410.     uint moved = pstack->body_size - count;
  411.     uint left;
  412.  
  413.     if (moved == 0)
  414.         return_error(e_Fatal);
  415.     memmove(bot + moved, bot, count * sizeof(ref));
  416.     left = used - moved;
  417.     memcpy(bot, body + left, moved * sizeof(ref));
  418.     refset_null_new(body + left, moved, 0);
  419.     r_dec_size(&pnext->used, moved);
  420.     pstack->p = pstack->top;
  421.     pstack->extension_used -= moved;
  422.     } else {
  423.     /*
  424.        * The contents of the two blocks will fit into a single block.
  425.        * Copy the used part of the top block to the top of the next
  426.        * block, and free the top block.
  427.      */
  428.     memcpy(body + used, bot, count * sizeof(ref));
  429.     pstack->bot = bot = body;
  430.     pstack->top = bot + pstack->body_size - 1;
  431.     gs_free_ref_array(pstack->memory, &pstack->current,
  432.               "ref_stack_pop_block");
  433.     pstack->current = next;
  434.     pstack->p = bot + (used + count - 1);
  435.     pstack->extension_size -= pstack->body_size;
  436.     pstack->extension_used -= used;
  437.     }
  438.     return 0;
  439. }
  440.  
  441. /*
  442.  * Extend a stack to recover from an overflow condition.
  443.  * May return overflow_error or e_VMerror.
  444.  */
  445. int
  446. ref_stack_extend(ref_stack_t *pstack, uint request)
  447. {
  448.     uint keep = (pstack->top - pstack->bot + 1) / 3;
  449.     uint count = pstack->p - pstack->bot + 1;
  450.     const ref_stack_params_t *params = pstack->params;
  451.  
  452.     if (request > params->data_size)
  453.     return_error(params->overflow_error);
  454.     if (keep + request > pstack->body_size)
  455.     keep = pstack->body_size - request;
  456.     if (keep > count)
  457.     keep = count;        /* required by ref_stack_push_block */
  458.     return ref_stack_push_block(pstack, keep, request);
  459. }
  460.  
  461. /*
  462.  * Push N empty slots onto a stack.  These slots are not initialized:
  463.  * the caller must immediately fill them.  May return overflow_error
  464.  * (if max_stack would be exceeded, or the stack has no allocator)
  465.  * or e_VMerror.
  466.  */
  467. int
  468. ref_stack_push(ref_stack_t *pstack, uint count)
  469. {
  470.     /* Don't bother to pre-check for overflow: we must be able to */
  471.     /* back out in the case of a VMerror anyway, and */
  472.     /* ref_stack_push_block will make the check itself. */
  473.     uint needed = count;
  474.     uint added;
  475.  
  476.     for (; (added = pstack->top - pstack->p) < needed; needed -= added) {
  477.     int code;
  478.  
  479.     pstack->p = pstack->top;
  480.     code = ref_stack_push_block(pstack,
  481.                     (pstack->top - pstack->bot + 1) / 3,
  482.                     added);
  483.     if (code < 0) {
  484.         /* Back out. */
  485.         ref_stack_pop(pstack, count - needed + added);
  486.         pstack->requested = count;
  487.         return code;
  488.     }
  489.     }
  490.     pstack->p += needed;
  491.     return 0;
  492. }
  493.  
  494. /*
  495.  * Push a block onto the stack, specifying how many elements of the current
  496.  * top block should remain in the top block and also how many elements we
  497.  * are trying to add.  Requires keep <= count.  May return overflow_error or
  498.  * e_VMerror.
  499.  */
  500. private int
  501. ref_stack_push_block(ref_stack_t *pstack, uint keep, uint add)
  502. {
  503.     const ref_stack_params_t *params = pstack->params;
  504.     uint count = pstack->p - pstack->bot + 1;
  505.     uint move = count - keep;
  506.     ref_stack_block *pcur = (ref_stack_block *) pstack->current.value.refs;
  507.     ref next;
  508.     ref_stack_block *pnext;
  509.     ref *body;
  510.     int code;
  511.  
  512.     if (keep > count)
  513.     return_error(e_Fatal);
  514.     /* Check for overflowing the maximum size, */
  515.     /* or expansion not allowed.  */
  516.     if (pstack->extension_used + (pstack->top - pstack->bot) + add >=
  517.     pstack->max_stack.value.intval ||
  518.     !params->allow_expansion
  519.     )
  520.     return_error(params->overflow_error);
  521.     code = gs_alloc_ref_array(pstack->memory, &next, 0,
  522.                   params->block_size, "ref_stack_push_block");
  523.     if (code < 0)
  524.     return code;
  525.     pnext = (ref_stack_block *) next.value.refs;
  526.     body = (ref *) (pnext + 1);
  527.     /* Copy the top keep elements into the new block, */
  528.     /* and make the new block the top block. */
  529.     init_block(pstack, &next, keep);
  530.     body += params->bot_guard;
  531.     memcpy(body, pstack->bot + move, keep * sizeof(ref));
  532.     /* Clear the elements above the top of the new block. */
  533.     refset_null_new(body + keep, params->data_size - keep, 0);
  534.     /* Clear the elements above the top of the old block. */
  535.     refset_null_new(pstack->bot + move, keep, 0);
  536.     pnext->next = pstack->current;
  537.     pcur->used.value.refs = pstack->bot;
  538.     r_set_size(&pcur->used, move);
  539.     pstack->current = next;
  540.     pstack->bot = body;
  541.     pstack->top = pstack->bot + pstack->body_size - 1;
  542.     pstack->p = pstack->bot + keep - 1;
  543.     pstack->extension_size += pstack->body_size;
  544.     pstack->extension_used += move;
  545.     return 0;
  546. }
  547.  
  548. /* Begin enumerating the blocks of a stack. */
  549. void
  550. ref_stack_enum_begin(ref_stack_enum_t *prse, const ref_stack_t *pstack)
  551. {
  552.     prse->block = (ref_stack_block *)pstack->current.value.refs;
  553.     prse->ptr = pstack->bot;
  554.     prse->size = pstack->p + 1 - pstack->bot;
  555. }
  556.  
  557. bool
  558. ref_stack_enum_next(ref_stack_enum_t *prse)
  559. {
  560.     ref_stack_block *block =
  561.     prse->block = (ref_stack_block *)prse->block->next.value.refs;
  562.  
  563.     if (block == 0)
  564.     return false;
  565.     prse->ptr = block->used.value.refs;
  566.     prse->size = r_size(&block->used);
  567.     return true;
  568. }
  569.  
  570. /* Clean up a stack for garbage collection. */
  571. void
  572. ref_stack_cleanup(ref_stack_t *pstack)
  573. {
  574.     ref_stack_block *pblock =
  575.     (ref_stack_block *) pstack->current.value.refs;
  576.  
  577.     refset_null_new(pstack->p + 1, pstack->top - pstack->p, 0);
  578.     pblock->used = pstack->current;    /* set attrs */
  579.     pblock->used.value.refs = pstack->bot;
  580.     r_set_size(&pblock->used, pstack->p + 1 - pstack->bot);
  581. }
  582.  
  583. /*
  584.  * Free the entire contents of a stack, including the bottom block.
  585.  * The client must still call ref_stack_free.  Note that after calling
  586.  * ref_stack_release, the stack is no longer usable.
  587.  */
  588. void
  589. ref_stack_release(ref_stack_t *pstack)
  590. {
  591.     gs_ref_memory_t *mem = pstack->memory;
  592.  
  593.     ref_stack_clear(pstack);
  594.     /* Free the parameter structure. */
  595.     gs_free_object((gs_memory_t *)mem, pstack->params,
  596.            "ref_stack_release(stack.params)");
  597.     /* Free the original (bottom) block. */
  598.     gs_free_ref_array(mem, &pstack->current, "ref_stack_release");
  599. }
  600.  
  601. /*
  602.  * Release a stack and then free the ref_stack object.
  603.  */
  604. void
  605. ref_stack_free(ref_stack_t *pstack)
  606. {
  607.     gs_memory_t *mem = (gs_memory_t *)pstack->memory;
  608.  
  609.     ref_stack_release(pstack);
  610.     gs_free_object(mem, pstack, "ref_stack_free");
  611. }
  612.  
  613. /* ------ Internal routines ------ */
  614.  
  615. /* Initialize the guards and body of a stack block. */
  616. private void
  617. init_block(ref_stack_t *pstack, const ref *psb, uint used)
  618. {
  619.     ref_stack_params_t *params = pstack->params;
  620.     ref *brefs = psb->value.refs;
  621.     uint i;
  622.     ref *p;
  623.  
  624.     for (i = params->bot_guard, p = brefs + stack_block_refs;
  625.      i != 0; i--, p++
  626.     )
  627.     ref_assign(p, ¶ms->guard_value);
  628.     /* The top guard elements will never be read, */
  629.     /* but we need to initialize them for the sake of the GC. */
  630.     /* We can use refset_null for this, because even though it uses */
  631.     /* make_null_new and stack elements must not be marked new, */
  632.     /* these slots will never actually be read or written. */
  633.     if (params->top_guard) {
  634.     ref *top = brefs + r_size(psb);
  635.     int top_guard = params->top_guard;
  636.  
  637.     refset_null_new(top - top_guard, top_guard, 0);
  638.     } {
  639.     ref_stack_block *const pblock = (ref_stack_block *) brefs;
  640.  
  641.     pblock->used = *psb;
  642.     pblock->used.value.refs = brefs + stack_block_refs + params->bot_guard;
  643.     r_set_size(&pblock->used, 0);
  644.     }
  645. }
  646.